//********************************************************************************************************
// Product Name: MapWindow.dll Alpha
// Description:  Low level interfaces that allow separate components to use objects that are defined
//               in completely independant libraries so long as they satisfy the basic interface requirements.
//********************************************************************************************************
// The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); 
// you may not use this file except in compliance with the License. You may obtain a copy of the License at 
// http://www.mozilla.org/MPL/ 
//
// Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF 
// ANY KIND, either express or implied. See the License for the specificlanguage governing rights and 
// limitations under the License. 
//
// The Original Code is MapWindow.Interfaces
//
// The Initial Developer of this Original Code is Ted Dunsford. Created in September, 2007.
// 
// Contributor(s): (Open source contributors should list themselves and their modifications here). 
//
//********************************************************************************************************
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using MapWindow.Main;
using MapWindow.Geometries;
using MapWindow.Data;
namespace MapWindow.Drawing
{
    /// <summary>
    /// A layer with drawing characteristics for LineStrings
    /// </summary>
    public class MapLineStringLayer: MapFeatureLayer, IMapLineStringLayer
    {
        /// <summary>
        /// The list of individual linestrings
        /// </summary>
        protected IEventList<IMapLineString> _MapLineStrings;

        /// <summary>
        /// The drawing characteristics
        /// </summary>
        protected ILineSymbolizer _LineSymbolizer;

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="featureLayer"></param>
        public MapLineStringLayer(IFeatureLayer featureLayer) : base(featureLayer)
        {
            _LineSymbolizer = new LineSymbolizer();
            base._FeatureLayer = featureLayer;        
            _MapLineStrings = new MapLineStringCollection(this);
        }

        /// <summary>
        /// Copies all the point symbol properties from any valid implementation of IPolygonSymbolizer
        /// like a MapPolygon
        /// </summary>
        /// <param name="copyFrom"></param>
        public void Copy(ILineSymbolizer copyFrom)
        {
            _LineSymbolizer.Copy(copyFrom);
        }

        /// <summary>
        /// This simply calls the draw function for each of its specific features, if it has them defined,
        /// or else it calls the default characteristics.
        /// TO DO: Support Symbols based on attributes
        /// </summary>
        /// <param name="g"></param>
        /// <param name="clipRect"></param>
        /// <param name="target"></param>
        public override void Draw(System.Drawing.Graphics g, System.Drawing.Rectangle clipRect, System.Drawing.Rectangle target)
        {
            _IsBusy = true;
            try
            {
                if (this.Visible == false)
                {
                    OnPaintCancelled(new OperationCanceledException("Visible was false"), g, clipRect, target);
                    return;
                }
              
                // The OnBeforePainting method can cancel the drawing
                if (OnBeforePainting(g, clipRect, target) == true)
                {
                    OnPaintCancelled(new OperationCanceledException("Canceled by OnBeforePainting"), g, clipRect, target);
                }

                
                IEnvelope view = new Envelope((double)g.ClipBounds.X, (double)g.ClipBounds.Right, (double)g.ClipBounds.Y, (double)g.ClipBounds.Bottom);
                double minW = view.Width / 1000;
                double minH = view.Height / 1000;
                for (int shp = 0; shp < Features.Count; shp++)
                {
                    if (_CancelDrawing == true)
                    {
                        OnPaintCancelled(new OperationCanceledException("CancelDrawing was true"), g, clipRect, target);
                       
                    }
                    
                    IEnvelope bounds = _MapLineStrings[shp].Envelope;
                    if (bounds.Intersects(view))
                    {
                        // Skip if the shape is too small to be drawn as more than a single pixel
                        if (bounds.Width < minW && bounds.Height < minH) continue;
                      
                        _MapLineStrings[shp].Draw(g, clipRect, target);
                    }
                }

              

            }
            catch (Exception ex)
            {
                // Only throw the event if this method was called directly, otherwise, pass up the exception
                OnPaintCancelled(ex, g, clipRect, target);
                
            }
            OnAfterPainting(g, clipRect, target);
           
        }


        #region Properties

        /// <summary>
        /// Gets or sets the list of pens to use when drawing this symbology
        /// </summary>
        public List<System.Drawing.Pen> FillPens
        {
            get { return _LineSymbolizer.FillPens; }
            set { _LineSymbolizer.FillPens = value; }
        }

        /// <summary>
        /// Gets an enumeration specifying Point because all MapPointLayers contain Point features
        /// </summary>
        public override FeatureTypes FeatureType
        {
            get
            {
                return FeatureTypes.Line;
            }
        }

        /// <summary>
        /// Gets or sets the FeatureSymbolizer determining the shared properties.  This is actually still the PointSymbolizer
        /// and should not be used directly on Polygons or Lines.
        /// </summary>
        /// <exception cref="System.InvalidOperationException">Unable to assign a non-point symbolizer to a MapPointLayer</exception>
        public override IFeatureSymbolizer FeatureSymbolizer
        {
            get
            {
                return (IFeatureSymbolizer)_LineSymbolizer;
            }
            set
            {
                if (value is ILineSymbolizer)
                {
                    _LineSymbolizer = (ILineSymbolizer)value;
                }
                else
                {
                    throw new InvalidOperationException("Unable to assign a non-line symbolizer to a MapPointLayer");
                }

            }
        }
       

       

        /// <summary>
        /// Gets or sets the default Line Symbolizer to use with all the lines on this layer.
        /// Setting this will not clear the existing individually specified Symbolizers,
        /// only the default symbolizer.
        /// </summary>
        public ILineSymbolizer LineSymbolizer
        {
            get { return _LineSymbolizer; }
            set { _LineSymbolizer = value; }
        }

        /// <summary>
        /// Gets or sets the collection of MapPoints that exists within this object.
        /// </summary>
        public virtual IEventList<IMapLineString> MapLineStrings
        {
            get { return _MapLineStrings; }
            set { _MapLineStrings = value; }
        }

       

        
       
        #endregion
    }
}
